﻿#region License
// MIT License
//
// Copyright(c) 2019-2025 ZhangYu
// https://gitee.com/zhangyu800/litebyte
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#endregion
#region Intro
// Purpose: Storage type info
// Author: ZhangYu
// CreateDate: 2019-12-10
// LastModifiedDate: 2025-02-07
#endregion
namespace LiteByte.Common {

    public class TypeData {

        #region Properties
        public string Name { get; } = "";
        public TypeName TypeCode { get; }
        public bool IsGeneric { get; }
        public bool IsList { get; }
        public bool IsHashMap { get; }
        public bool IsArray { get; }
        public bool IsNumberType { get; }
        public bool IsBaseType { get; }
        public bool IsClass { get; }
        public bool IsStruct { get; }
        public TypeData ElementType { get; }
        public List<TypeData> GenericTypes { get; }
        public List<FieldData> Fields { get; } = new List<FieldData>();
        public int Size { get; }
        #endregion

        #region Constructors
        public TypeData() {
            IsClass = true;
        }

        public TypeData(string name, bool isStruct) {
            IsStruct = isStruct;
            IsClass = !isStruct;
            Name = name;
        }

        /// <summary> 基本类型 </summary>
        public TypeData(string name, TypeName typeCode) {
            TypeCode = typeCode;
            switch (typeCode) {
                case TypeName.Bit1 or TypeName.Bit2 or TypeName.Bit3 or TypeName.Bit4 or TypeName.Bit5 or TypeName.Bit6 or TypeName.Bit7 or TypeName.Bit8 or
                     TypeName.Bool or TypeName.Char or
                     TypeName.UInt8 or TypeName.UInt16 or TypeName.UInt32 or TypeName.UInt64 or
                     TypeName.Int8 or TypeName.Int16 or TypeName.Int32 or TypeName.Int64 or
                     TypeName.Float16 or TypeName.Float32 or TypeName.Float64 or
                     TypeName.Decimal or TypeName.DateTime or
                     TypeName.VUInt16 or TypeName.VUInt32 or TypeName.VUInt64 or
                     TypeName.VInt16 or TypeName.VInt32 or TypeName.VInt64:
                    IsStruct = true;
                    IsBaseType = true;
                    IsNumberType = true;
                    break;
                case TypeName.ASCII or TypeName.UTF8 or TypeName.UTF16 or TypeName.UTF32 or TypeName.GBK or TypeName.VUnicode:
                    IsClass = true;
                    IsBaseType = true;
                    break;
                default:
                    IsClass = true;
                    break;
            }
            Name = name;
            Size = (int)Math.Ceiling(CommonUtil.GetByteSize(typeCode));
        }

        /// <summary> 数组 </summary>
        public TypeData(string name, TypeData elementType) {
            IsClass = true;
            IsArray = true;
            Name = name;
            ElementType = elementType;
            Size = elementType.Size * 4;
        }

        /// <summary> 泛型 </summary>
        public TypeData(string name, List<TypeData> genericTypes, bool isList, bool isHashMap) {
            Name = name;
            IsClass = true;
            IsGeneric = true;
            IsList = isList;
            IsHashMap = isHashMap;
            GenericTypes = genericTypes;
            if (isList) {
                Size = GetListPredictSize();
            } else if (isHashMap) {
                Size = GetHashMapPredictSize();
            }
        }

        /// <summary> 自定义类型 </summary>
        public TypeData(string name, List<FieldData> fields, bool isStruct) {
            IsClass = !isStruct;
            IsStruct = isStruct;
            Name = name;
            Fields = fields;
            for (int i = 0; i < fields.Count; i++) {
                Size += fields[i].Type.Size;
            }
        }
        #endregion

        #region ToString
        public override string ToString() {
            return Name;
        }
        #endregion

        #region Tools
        /// <summary> 获取List预计大小 </summary>
        private int GetListPredictSize() {
            return GenericTypes[0].Size * 4;
        }

        /// <summary> 获取HashMap预估大小 </summary>
        private int GetHashMapPredictSize() {
            TypeData keyType = GenericTypes[0];
            TypeData valueType = GenericTypes[1];
            return (keyType.Size + valueType.Size) * 4;
        }
        #endregion

    }

}